package com.crc.luojian.factory.impl;

import com.crc.luojian.beans.model.BeanDefinition;
import com.crc.luojian.factory.ObjectFactory;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @program: luojian-springframework
 * @description:
 * @author: luojian58
 * @create: 2021-06-10 10:59
 */
public class SingletonBeanRegistery {

    private static final Object NULL_OBJECT = new Object();
    //一级缓存,也就是单例池
    private final Map<String,Object> singletonObjects = new ConcurrentHashMap<>();

    // 二级缓存，未完全初始化完全的对象

    private final Map<String,Object> earlySigletonObjects = new ConcurrentHashMap<>();

    //三级缓存，SingletonFactories 放的是一个工厂 该工厂用来创建代理对象
    private final Map<String, ObjectFactory<?>> singletonFactories = new ConcurrentHashMap<>();

    private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>());

    private Map<String, BeanDefinition> dependentBeanMap = new ConcurrentHashMap<String, BeanDefinition>();
    private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
    /**
     * @Author luojian
     * @Description  不传bean 工厂获取bean allowEarlyReference 是否获取提前引用
     * @Date  2021/6/10 12:08
     * @Param [beanName, allowEarlyReference]
     * @return java.lang.Object
     **/
    protected Object getSingleton(String beanName,boolean allowEarlyReference){
        Object singletonObject = singletonObjects.get(beanName);
        //如果单例池中没有这个对象，并且当前对象正在创建中
        if(singletonObject == null  && isSingletonCurrentlyInCreation(beanName)){
            synchronized (singletonObjects){
                singletonObject = earlySigletonObjects.get(beanName);
                if(singletonObject == null && allowEarlyReference){
                    ObjectFactory<?> singletonFactory= singletonFactories.get(beanName);
                    if(singletonFactory != null){
                        singletonObject = singletonFactory.getObject();
                        this.earlySigletonObjects.put(beanName,singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return  singletonObject != NULL_OBJECT ? singletonObject : null;
    }

    /**
     * @Author luojian
     * @Description  通过工厂获取单例对象
     * @Date  2021/6/10 12:24
     * @Param [beanName, factory]
     * @return java.lang.Object
     **/
    protected Object getSingleton(String beanName,ObjectFactory factory){
        synchronized (singletonObjects){
            Object singletonObject = singletonObjects.get(beanName);
            if(singletonObject == null) {
                singletonsCurrentlyInCreation.add(beanName);
                singletonObject = factory.getObject();
                singletonsCurrentlyInCreation.remove(beanName);
                addSingleton(beanName,singletonObject);
            }
            return (singletonObject != NULL_OBJECT ? singletonObject : null);
        }
    }

    protected boolean isSingletonCurrentlyInCreation(String beanName) {
        return singletonsCurrentlyInCreation.contains(beanName);
    }

    /**
     * @Author luojian
     * @Description  判断单例池中是否有这个bean
     * @Date  2021/6/10 14:22
     * @Param [beanName]
     * @return boolean
     **/
    public boolean containsSingleton(String beanName){
        return  this.singletonObjects.containsKey(beanName);
    }

    /**
     * @Author luojian
     * @Description 
     * @Date  2021/6/10 14:33
     * @Param [beanName, singletonObject]
     * @return void
     **/
    protected void addSingleton(String beanName, Object singletonObject) {
        synchronized (this.singletonObjects) {
            this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
            this.singletonFactories.remove(beanName);
            this.earlySigletonObjects.remove(beanName);
        }
    }
    /**
     * @Author luojian
     * @Description 将提前引用的beanfactory 放入到三级缓存中
     * @Date  2021/6/10 14:34
     * @Param [beanName, singletonFactory]
     * @return void
     **/
    protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
        synchronized (this.singletonObjects) {
            if (!this.singletonObjects.containsKey(beanName)) {
                this.singletonFactories.put(beanName, singletonFactory);
                this.earlySigletonObjects.remove(beanName);
            }
        }
    }


    /**
     * @Author luojian
     * @Description 依赖bean
     * @Date  2021/6/10 14:02
     * @Param [beanName, dependentBeanName]
     * @return void
     **/
/*    public void registerDependentBean(String beanName, String dependentBeanName) {

        synchronized (this.dependentBeanMap) {
            Set<String> dependentBeans =
                    this.dependentBeanMap.computeIfAbsent(beanName, k -> {
                        return new LinkedHashSet<>(8);
                    });
            if (!dependentBeans.add(dependentBeanName)) {
                return;
            }
        }

        synchronized (this.dependenciesForBeanMap) {
            Set<String> dependenciesForBean =
                    this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
            dependenciesForBean.add(beanName);
        }
    }*/
}
